package com.hw.one.peach.da.service;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Properties;

import org.apache.commons.net.ftp.FTP;
import org.apache.commons.net.ftp.FTPClient;
import org.apache.commons.net.ftp.FTPClientConfig;
import org.apache.commons.net.ftp.FTPFile;
import org.apache.commons.net.ftp.FTPReply;

public class FtpClientUtils {

	private FTPClient ftp;

	/**
	 * 初始化构造器
	 * 登录ftp
	 * <p>
	 * ftp使用完毕必须调用<b>disconnect()</b>方法关闭连接
	 * </p>
	 */
	public FtpClientUtils() throws Exception {
		Properties p = new Properties();
		p.load(FtpClientUtils.class.getClassLoader().getResourceAsStream("ext/conf/ftpclient.properties"));
		
		String url = p.getProperty("ftpserver.ip");
		int port = Integer.parseInt(p.getProperty("ftpserver.port"));
		String username = p.getProperty("ftpserver.username");
		String password = p.getProperty("ftpserver.password");
		ftp = new FTPClient();
		ftp.connect(url, port);
		ftp.login(username, password);
	}
	
	/**
	 * 初始化构造器
	 * 登录ftp
	 * <p>
	 * ftp使用完毕必须调用<b>disconnect()</b>方法关闭连接
	 * </p>
	 * @param url
	 * @param port
	 * @param username
	 * @param password
	 * @throws Exception
	 * 
	 */
	public FtpClientUtils(String url, int port, String username, String password) throws Exception {
		ftp = new FTPClient();
		ftp.connect(url, port);
		ftp.login(username, password);
	}

	/**
	 * 释放FTP
	 */
	public void disconnect() {
		if (ftp.isAvailable()) {
			try {
				ftp.logout(); // 退出FTP
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
		if (ftp.isConnected()) {
			try {
				// 断开连接
				ftp.disconnect();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
	}

	/**
	 * 移动文件.
	 * 
	 * @param sourceFileName
	 * @param targetFile
	 * @throws IOException
	 */
	public void moveFile(String sourceFileName, String sourceDir, String targetDir) throws IOException {
		ByteArrayInputStream in = null;
		ByteArrayOutputStream fos = new ByteArrayOutputStream();
		try {
			ftp.enterLocalPassiveMode();
			ftp.setFileType(FTP.BINARY_FILE_TYPE);
			// 目录切换
			String[] dirs = sourceDir.split("/");
			for (String dir : dirs) {
				dir = new String(dir.getBytes("GBK"), "UTF-8");
				ftp.makeDirectory(dir);
				ftp.changeWorkingDirectory(dir);
			}
			
			ftp.setBufferSize(1024 * 2);
			// 将文件读到内存中
			ftp.retrieveFile(new String(sourceFileName.getBytes("GBK"), "iso-8859-1"), fos);
			ftp.deleteFile(sourceFileName);
			in = new ByteArrayInputStream(fos.toByteArray());
			if (in != null) {
				dirs = targetDir.split("/");
				for (String dir : dirs) {
					dir = new String(dir.getBytes("GBK"), "UTF-8");
					ftp.makeDirectory(dir);
					ftp.changeWorkingDirectory(dir);
				}
				ftp.storeFile(new String(sourceFileName.getBytes("GBK"), "iso-8859-1"), in);
			}
		} finally {
			// 关闭流
			if (in != null) {
				in.close();
			}
			if (fos != null) {
				fos.close();
			}
		}
	}


	/**
	 * 上传文件
	 * @param path ftp路径
	 * @param filename 存放到ftp的文件名
	 * @param is 文件流
	 * @return
	 */
	public boolean uploadFile(String path, String filename, InputStream is) {
		boolean success = false;
		OutputStream out = null;
		try {
			if (ftp != null && FTPReply.isPositiveCompletion(ftp.getReplyCode())) {
				// ftp.enterLocalActiveMode(); 此种方式OutputStream为null
				ftp.enterLocalPassiveMode();
				ftp.setFileType(FTP.BINARY_FILE_TYPE);
				// 目录切换
				String[] dirs = path.split("/");
				for (String dir : dirs) {
					dir = new String(dir.getBytes("GBK"), "UTF-8");
					ftp.makeDirectory(dir);
					ftp.changeWorkingDirectory(dir);
				}
				// 上传文件
				filename = new String(filename.getBytes("GBK"), "UTF-8");
				out = ftp.storeFileStream(filename);
				byte[] byteArray = new byte[4096];
				int read = 0;
				while ((read = is.read(byteArray)) != -1) {
					out.write(byteArray, 0, read);
				}
				out.flush();
				success = true;
			}
		} catch (IOException e) {
			e.printStackTrace();
		} finally {
			try {
				if (out != null) {
					out.flush();
					out.close();
					out = null;
				}
				if (is != null) {
					is.close();
					is = null;
				}
			} catch (IOException e) {
			}
		}
		return success;
	}

	// 递归删除目录
	private void loopdel(FTPFile file) throws IOException {
		if (file.isDirectory()) {
			ftp.changeWorkingDirectory(new String(file.getName().getBytes("GBK"), "UTF-8"));
			FTPFile[] fls = ftp.listFiles();
			if (fls.length > 0) {
				for (int i = 0; i < fls.length; i++) {
					loopdel(fls[i]);
				}
				ftp.changeToParentDirectory();
				ftp.removeDirectory(file.getName());
			} else {
				ftp.changeToParentDirectory();
				ftp.removeDirectory(file.getName());
			}
		} else {
			ftp.deleteFile(file.getName());
		}
	}

	/**
	 * 删除指定目录
	 * 
	 * @param dir d/s/f 删除f文件夹 包括下面的文件及文件夹
	 * @return
	 */
	public boolean deleteDirectory(String directory) {
		boolean success = false;
		try {
			ftp.enterLocalPassiveMode();
			ftp.setControlEncoding("UTF-8");
			FTPClientConfig conf = new FTPClientConfig(FTPClientConfig.SYST_UNIX);
			conf.setServerLanguageCode("zh");
			ftp.configure(conf);
			String[] dirs = directory.split("/");
			String dir = "";
			for (int i = 0; i < dirs.length - 1; i++) {
				dir = new String(dirs[i].getBytes("GBK"), "UTF-8");
				if (!ftp.changeWorkingDirectory(dir)) {
					return false;
				}
			}

			ftp.changeWorkingDirectory(dirs[dirs.length - 1]);
			FTPFile[] fls = ftp.listFiles();
			for (FTPFile ftpFile : fls) {
				loopdel(ftpFile);
			}
			ftp.changeToParentDirectory();
			ftp.removeDirectory(dirs[dirs.length - 1]);
		} catch (IOException e) {
			e.printStackTrace();
		} finally {
		}

		return success;
	}

	/**
	 * 删除FTP文件
	 * 
	 * @param filename
	 *            a/b/c/test.txt 删除test.txt文件
	 * @return
	 */
	public boolean deleteFile(String filename) {
		boolean success = false;
		try {
			ftp.enterLocalPassiveMode();
			String[] dirs = filename.split("/");
			String dir = "";
			for (int i = 0; i < dirs.length - 1; i++) {
				dir = new String(dirs[i].getBytes("GBK"), "UTF-8");
				if (!ftp.changeWorkingDirectory(dir)) {
					return false;
				}
			}

			ftp.deleteFile(new String(dirs[dirs.length - 1].getBytes("GBK"), "UTF-8"));
			success = true;
		} catch (IOException e) {
			e.printStackTrace();
		} finally {
		}
		return success;
	}

	/**
	 * 下载FTP文件
	 * 
	 * @param filename
	 *            a/b/c/test.txt 下载test.txt文件
	 * @return
	 * @throws Exception
	 */
	public InputStream downFile(String filename) {
		try {
			ftp.enterLocalPassiveMode();
			ftp.setFileType(FTP.BINARY_FILE_TYPE);
			String[] dirs = filename.split("/");
			String dir = "";
			for (int i = 0; i < dirs.length - 1; i++) {
				dir = new String(dirs[i].getBytes("GBK"), "UTF-8");
				if (!ftp.changeWorkingDirectory(dir)) {
					return null;
				}
			}
			for (FTPFile file : ftp.listFiles()) {
				if (file.getName().equals(new String(dirs[dirs.length - 1].getBytes("GBK"), "UTF-8"))) {
					return ftp.retrieveFileStream(file.getName());
				}
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
		return null;
	}

	public List<Map<String, Object>> fileList(String directory) throws Exception{
		List<Map<String, Object>> data = new ArrayList<Map<String, Object>>();
		Map<String, Object> map = new HashMap<String, Object>();
		
		ftp.enterLocalPassiveMode();
		ftp.setFileType(FTP.BINARY_FILE_TYPE);
		String[] dirs = directory.split("/");
		String dir = "";
		for (int i = 0; i < dirs.length; i++) {
			dir = new String(dirs[i].getBytes("GBK"), "UTF-8");
			if (!ftp.changeWorkingDirectory(dir)) {
				return data;
			}
		}
		SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
		for (FTPFile file : ftp.listFiles()) {
			if (file.isFile()) {
				map = new HashMap<String, Object>();
				map.put("name", file.getName());
				map.put("size", file.getSize());
				map.put("time", sdf.format(file.getTimestamp().getTime()));
				data.add(map);
			}
		}
		return data;
	}
	
	public static void main(String[] args) throws Exception {
		/** 初始化打开连接 */
		FtpClientUtils ftp = new FtpClientUtils("10.0.16.11", 30021, "admin", "admin");
//		/** 上传 */
//		ftp.uploadFile("", "2018051716.zip", new FileInputStream("E:\\2018051716.zip"));
//		/** 删除文件夹 */
//		ftp.deleteDirectory("新建文件夹");
//		/** 删除文件 */
//		ftp.deleteFile("2018051716.zip");
//		/** 下载 */
//		InputStream in = ftp.downFile("2018051716.zip");
//		OutputStream os = new FileOutputStream("E:\\2018051716.zip");
//		byte[] byteArray = new byte[4096];
//		int read=0;
//		while((read=in.read(byteArray)) != -1) {
//			os.write(byteArray,0,read);
//		}
//		os.flush();
//		os.close();
//		/** 遍历文件夹获取文件列表 */
//		List<Map<String, Object>> data = ftp.fileList("");
//		for (Map<String, Object> map : data) {
//			System.out.println(map);
//		}
		
		ftp.moveFile("41010300040000001_VOCS001_2018070317.D.zip", "", "correction");
		/** 关闭连接 */
		ftp.disconnect();
	}
}
